/*
 * ./src/fonction_connection.c
 * Copyright (C) 2009 lameire alexis
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include "fonction_connection.h"
#include "fonction_threads.h"

void kick(irc_session_t * session, const char **params, const const char *origin, donnee_de_control * jeux, size_t taille_commande)
{
	printf(_("DEBUG : Kick demandé\n"));
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		size_t taille_params = 0;
		char *debut_pseudo = NULL;
		size_t taille_pseudo = 0;
		size_t taille_raison = 0;
		char *pseudo_a_kicker = NULL;
		char *raison_du_kick = NULL;
		char carractere_lu = 'x';

		while (carractere_lu != ' ' && carractere_lu != '\0')
		{
			carractere_lu = params[1][taille_commande + 1 + taille_pseudo];
			taille_pseudo++;
		}
		taille_raison = strlen(&params[1][taille_commande + taille_pseudo]);

		printf(_("DEBUG : Taille raison : %d, Taille pseudo : %d\n"), taille_raison, taille_pseudo);
		pseudo_a_kicker = malloc(sizeof(char) * taille_pseudo);
		raison_du_kick = malloc(sizeof(char) * taille_raison);
		if (pseudo_a_kicker == NULL || raison_du_kick == NULL)
		{
			fprintf(stderr, _("ERREUR : Impossible d'allouer la mémoire pour le kick"));
			exit(EXIT_FAILURE);
		}
		else
		{
			strcpy(raison_du_kick, &params[1][taille_commande + taille_pseudo]);
			strncpy(pseudo_a_kicker, &params[1][taille_commande + 1], taille_pseudo - 1);
			pseudo_a_kicker[taille_pseudo - 1] = '\0';
			jeux->raison_du_kick = raison_du_kick;
			jeux->pseudo_a_kicker = pseudo_a_kicker;
			printf(_("DEBUG : Pseudo à kicker : '%s-'\n"), jeux->pseudo_a_kicker);
			printf(_("DEBUG : Raison du kick : '%s'\n"), jeux->raison_du_kick);

			// preparation de la recuperation des pseudos
			irc_cmd_names(session, jeux->config_prog->chan);
			jeux->recherche_pseudo_kick = 1;
		}
	}
}

int verifier_leader(donnee_de_control * jeux, const char *origin, irc_session_t * session, unsigned char flag)
{
	if ((flag & SAVE_TO_LEADER) != 0 && strcmp(origin, jeux->pseudo_leader) != 0)
	{
		int taille_pseudo = strlen(origin);
		char *pseudo = malloc(sizeof(char) * (taille_pseudo + 1));

		if (pseudo == NULL)
		{
			fprintf(stderr, _("Erreur : Impossible d'allouer la mémoire pour le pseudo"));
			exit(EXIT_FAILURE);
		}
		else
		{
			if (jeux->pseudo_joueur_leader != NULL)
			{
				free(jeux->pseudo_joueur_leader);
			}
			strcpy(pseudo, origin);
			jeux->pseudo_joueur_leader = pseudo;
		}
	}

	if (jeux->pseudo_joueur_leader && strcmp(jeux->pseudo_joueur_leader, origin) == 0)
	{
		if ((flag & NEED_ADMIN) != 0 && (flag & NEED_LEADER) == 0)
		{
			irc_cmd_notice(session, origin,
				       _
				       ("De grands pouvoirs impliquent de grandes responsabilités, et manifestement, tu n'as pas l'étoffe d'un chef."));
			return 0;
		}
		else
		{
			return 1;
		}
	}
	else if (strcmp(jeux->pseudo_leader, origin) == 0)
	{
		if (jeux->password_valider)
		{
			return 1;
		}
		else
		{
			irc_cmd_notice(session, origin, _("\x02\00305Le pseudo n'a pas encore été validé avec !password"));
			return 0;
		}
	}
	else
	{
		irc_cmd_notice(session, origin, _("\x02\00305Ce n'est pas ton rôle, laisse ça au leader, petit esclave."));
		return 0;
	}
}

mot_existe *verif_ajouter_et_retirer(irc_session_t * session, const char **params, const const char *origin, donnee_de_control * jeux,
				     size_t taille_commande)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		FILE *fichier = NULL;
		fichier = fopen("DB.txt", "r+");
		if (fichier == NULL)
		{
			fprintf(stderr, _("ERREUR : Impossible d'ouvrir le fichier de configuration : fermeture"));
			exit(EXIT_FAILURE);
		}
		else
		{
			int taille_fichier = strlen(params[1] + taille_commande + 1);
			char *mot = NULL;
			mot = malloc(sizeof(char) * (taille_fichier + 1));
			if (mot == NULL)
			{
				fprintf(stderr, _("ERREUR : Impossible d'allouer de la mémoire pour la recherche du mot : fermeture"));
				fclose(fichier);
				exit(EXIT_FAILURE);
			}
			else
			{
				int debut_mot = 0;
				mot_existe *structure_a_retourner = NULL;

				strcpy(mot, params[1] + taille_commande + 1);
				couper_espace(mot);
				structure_a_retourner = malloc(sizeof(mot_existe));
				if (structure_a_retourner == NULL)
				{
					fprintf(stderr, _("ERREUR : Impossible d'allouer la structure de retour\n"));
					free(mot);
					fclose(fichier);
					exit(EXIT_FAILURE);
				}
				else
				{
					structure_a_retourner->fichier = fichier;
					structure_a_retourner->mot = mot;
					if ((debut_mot = verifier_mot(fichier, mot)) >= 0)
					{
						structure_a_retourner->existance = 1;
					}
					else
					{
						structure_a_retourner->existance = 0;
					}
					structure_a_retourner->debut_mot = debut_mot;
					return structure_a_retourner;
				}
			}
		}
	}
}

void free_mot_existe(mot_existe * structure)
{
	free(structure->mot);
	if (structure->fichier != NULL)
	{
		fclose(structure->fichier);
	}
	free(structure);
}

void cmd_debut_inscription(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN | NEED_LEADER | SAVE_TO_LEADER))
	{
		if (jeux->parti_en_cour == 0)
		{
			irc_cmd_msg(session, jeux->config_prog->chan, _("\x02\00303D'accord, veuillez vous inscrire."));
			jeux->inscription_ouverte = 1;
			hl_users(session, jeux->config_prog->chan);
		}
		else
		{
			irc_cmd_msg(session, jeux->config_prog->chan, _("\x02\00305Opération impossible : une partie est déjà en cours."));
		}
	}

}

void cmd_inscription(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	printf(_("DEBUG : demande d'inscription\n"));
	if (jeux->leader == 0)
	{
		irc_cmd_msg(session, jeux->config_prog->chan, _("\x02\00305Veuillez choisir un leader au préalable."));
	}
	else if (jeux->inscription_ouverte == 0 && jeux->parti_en_cour == 0)
	{
		irc_cmd_msg(session, jeux->config_prog->chan, _("\x02\00305Veuillez lancer une partie avec !debut_inscription."));
	}
	/*
	   else if (strncmp(origin, jeux->pseudo_leader, 30) == 0)
	   {
	   irc_cmd_msg(session, jeux->config_prog->chan, _("operation impossible : le leader ne peut pas jouer"));
	   } 
	 */
	else
	{
		int i = 0;
		char *tmp;
		participent *joueur_a_verifier = jeux->joueurs;

		//verification de la présence d'un joueur
		for (i = 0; i != jeux->nb_inscrits; i++)
		{
			if (strcmp(origin, joueur_a_verifier->pseudo) == 0)
			{
				printf(_("DEBUG : Demande d'inscription rejetée\n"));
				return;
			}
			joueur_a_verifier = joueur_a_verifier->joueur_suivent;
		}

		//alocation d'un nouveau participent
		participent *joueur;
		joueur = malloc(sizeof(participent));
		if (joueur == NULL)
		{
			fprintf(stderr, _("ERREUR : Allocation dynamique de mémoire pour un participant refusée : fermeture\n"));
			exit(EXIT_FAILURE);
		}

		//création d'une entrée pour la liste chainée et copie
		memset(joueur, 0, sizeof(participent));
		strcpy(joueur->pseudo, origin);
		jeux->nb_inscrits++;

		//envois de la confirmation d'inscription
		tmp = (char *) g_strdup_printf(_("\x02\00302%d joueur(s) inscrit(s)"), jeux->nb_inscrits);
		irc_cmd_msg(session, jeux->config_prog->chan, tmp);
		g_free(tmp);

		//ajout a la liste chainée
		if (jeux->joueurs == 0)
		{
			jeux->joueurs = joueur;
		}
		else
		{
			joueur->joueur_suivent = jeux->joueurs;
			jeux->joueurs = joueur;
		}

		//passage du voice
		tmp = (char *) g_strdup_printf("+v %s", origin);
		irc_cmd_channel_mode(session, jeux->config_prog->chan, tmp);
		g_free(tmp);

	}
}

void cmd_passer(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (!strcmp(origin, jeux->pseudo_compteur) || verifier_leader(jeux, origin, session, NEED_LEADER | NEED_ADMIN))
	{
		if (jeux->parti_en_cour)
		{
			char *phrase = NULL;
			int i = 0;

			if (!strcmp(origin, jeux->pseudo_compteur))
			{
				jeux->nb_passer++;
			}
			//affichage du mot précédent
			phrase = (char *) g_strdup_printf(_("\x02\00302Le mot était : %s"), jeux->mot_a_deviner);
			irc_cmd_msg(session, jeux->config_prog->chan, phrase);
			g_free(phrase);

			//librération du mot précédent et tirrage d'un mot
			free(jeux->mot_a_deviner);
			jeux->mot_a_deviner = tirer_un_mot(jeux->config_prog->def_cat);

			//tirage d'un nouveau pseudo
			if (jeux->nb_passer > 5 || jeux->timeout == 1)
			{
				int no_joueur = 0;
				participent *info_joueur = jeux->joueurs;

				if (jeux->timeout)
				{
					jeux->timeout = 0;
					irc_cmd_msg(session, jeux->config_prog->chan, _("Timeout atteint : changement de mot et de joueur"));
				}
				else
				{
					jeux->nb_passer = 0;
					irc_cmd_msg(session, jeux->config_prog->chan, _("5 tirages effectués : changement de participent"));
				}

				//tirage au sort 
				no_joueur = rand() % jeux->nb_inscrits;

				//selection du joueur tirer
				for (i = 0; i != no_joueur; i++)
				{
					info_joueur = info_joueur->joueur_suivent;
				}

				//copie du pseudo
				strcpy(jeux->pseudo_compteur, info_joueur->pseudo);

				//information sur la joueur qui commence
				phrase = (char *) g_strdup_printf(_("Le joueur qui fait deviner est maintenent %s."), jeux->pseudo_compteur);
				irc_cmd_msg(session, jeux->config_prog->chan, phrase);
				g_free(phrase);
			}

			//affichage de la phrase
			phrase = (char *) g_strdup_printf(_("\x02Le mot a faire deviner est : %s"), jeux->mot_a_deviner);
			irc_cmd_notice(session, jeux->pseudo_compteur, phrase);
			irc_cmd_notice(session, jeux->pseudo_leader, phrase);
			g_free(phrase);

			//intialisation du timeout
			init_thread_timeout(jeux, origin, session);
		}
		else
		{
			irc_cmd_msg(session, jeux->config_prog->chan, _("une partie n'est pas en cour"));
		}
	}
}

void cmd_stop(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_LEADER | NEED_ADMIN))
	{
		int i = 0;
		char *phrase = NULL;
		participent *joueur = jeux->joueurs;

		irc_cmd_msg(session, jeux->config_prog->chan, _("Fin de la partie."));

		for (i = 0; i != jeux->nb_inscrits; i++)
		{
			participent *joueur_a_free = NULL;

			//affichage du score
			phrase = (char *) g_strdup_printf("%s : %d", joueur->pseudo, joueur->points);
			irc_cmd_msg(session, jeux->config_prog->chan, phrase);
			g_free(phrase);

			//enlevement du voice
			phrase = (char *) g_strdup_printf("-v %s", joueur->pseudo);
			irc_cmd_channel_mode(session, jeux->config_prog->chan, phrase);
			g_free(phrase);

			//mise a jour des scores
			ajouter_score(joueur->pseudo, joueur->points);

			//passage au joueur suivent et déréférencement
			joueur_a_free = joueur;
			joueur = joueur->joueur_suivent;
			free(joueur_a_free);
		}
		//libération du mot
		free(jeux->mot_a_deviner);

		//libération du role de joueur leader
		if (jeux->pseudo_joueur_leader)
		{
			free(jeux->pseudo_joueur_leader);
			jeux->pseudo_joueur_leader;
		}

		//affichage du flag de fin de partie
		jeux->parti_en_cour = 0;
		jeux->inscription_ouverte = 0;
		jeux->nb_passer = 0;
		jeux->compteur_mot++;

		//mise a zerro du nombre de joueur
		jeux->nb_inscrits = 0;

		//enlevement de l'etat d'halfop
		phrase = (char *) g_strdup_printf("-h %s", jeux->pseudo_leader);
		irc_cmd_channel_mode(session, jeux->config_prog->chan, phrase);
		g_free(phrase);

		//enlevement du mode modered
		irc_cmd_channel_mode(session, jeux->config_prog->chan, "-m");

	}
}

void cmd_score(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (!jeux->parti_en_cour)
	{
		irc_cmd_notice(session, origin, _("Commande invalide : Aucune partie en cours."));
	}
	else
	{
		int i = 0;
		participent *joueur = jeux->joueurs;
		for (i = 0; i != jeux->nb_inscrits; i++)
		{
			char *phrase = NULL;

			phrase = (char *) g_strdup_printf(_("%s : %d points"), joueur->pseudo, joueur->points);
			irc_cmd_msg(session, origin, phrase);
			g_free(phrase);

			joueur = joueur->joueur_suivent;
		}
	}
}

void cmd_sha1sum(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	int taille_phrase = strlen(&params[1][taille_cmd + 1]);
	char *phrase = NULL;

	phrase = malloc(sizeof(char) * (taille_phrase + 1));
	if (phrase == NULL)
	{
		fprintf(stderr, _("ERREUR : Impossible d'allouer la chaîne à checksummer"));
		exit(EXIT_FAILURE);
	}
	else
	{
		char *somme_sha1 = NULL;
		char *phrase_a_afficher = NULL;

		//copie de la chaine et prepration
		strcpy(phrase, &params[1][taille_cmd + 1]);
		couper_espace(phrase);

		//calcul de la somme de control
		somme_sha1 = sha1sun(phrase);

		//affichage
		phrase_a_afficher = (char *) g_strdup_printf("%s %s", somme_sha1, phrase);
		irc_cmd_notice(session, origin, phrase_a_afficher);
		g_free(phrase_a_afficher);

		//liberation
		free(somme_sha1);
		free(phrase);
	}
}

void cmd_dit(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		irc_cmd_msg(session, jeux->config_prog->chan, &params[1][taille_cmd + 1]);
	}
}

void cmd_definir_leader(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		if (!parse_regex("^[-_[:alnum:]]{1,31}", &params[1][taille_cmd + 1]))
		{
			irc_cmd_msg(session, jeux->config_prog->chan, _("ERREUR : Pseudo invalide"));
		}
		else
		{
			char *phrase = NULL;

			//enlévement de l'ancien halfop
			phrase = (char *) g_strdup_printf("-h %s", jeux->pseudo_leader);
			irc_cmd_channel_mode(session, jeux->config_prog->chan, phrase);
			jeux->password_valider = 0;

			//passage du mode halfop
			phrase = (char *) g_strdup_printf("+h %s", origin);
			irc_cmd_channel_mode(session, jeux->config_prog->chan, phrase);
			g_free(phrase);

			//definition du leader
			strncpy(jeux->pseudo_leader, &params[1][taille_cmd + 1], 30);
			couper_espace(jeux->pseudo_leader);

			//confirmation a l'utilisateur de la definition du leader
			phrase = (char *) g_strdup_printf(_("\x02\00303Le leader est maintenant %s."), jeux->pseudo_leader);
			irc_cmd_msg(session, jeux->config_prog->chan, phrase);
			g_free(phrase);
		}
	}
}

void cmd_ok(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_LEADER | NEED_ADMIN))
	{
		int i = 0;
		int taille_pseudo = strlen(&params[1][taille_cmd + 1]);
		char *pseudo_a_valider = NULL;

		pseudo_a_valider = malloc(sizeof(char) * (taille_pseudo + 1));

		if (pseudo_a_valider == NULL)
		{
			fprintf(stderr, _("Impossible d'allouer de la mémoire pour le pseudo : fermeture\n"));
			exit(EXIT_FAILURE);
		}
		else
		{
			//recherche du pseudo a valider
			strcpy(pseudo_a_valider, &params[1][taille_cmd + 1]);
			couper_espace(pseudo_a_valider);

			valider_pseudo(session, jeux, pseudo_a_valider);
		}
	}
}


void cmd_kickban(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	kick(session, params, origin, jeux, taille_cmd);
	jeux->recherche_pseudo_ban = 1;

}

void cmd_kick(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	kick(session, params, origin, jeux, taille_cmd);
}

void cmd_ajouter(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		sqlite3 *db = NULL;
		int erreur = 0;
		int taille_mot = 0;
		int id_cat = -1;
		char *mot = NULL;
		char *categorie = NULL;

		//recupération du mot et de la categorie
		erreur = recuperer_args_ajouter(&params[1][taille_cmd + 1], &categorie, &mot);
		couper_espace(mot);
		printf(_("DEBUG : Mot à ajouter : %s\n"), mot);
		if (erreur)
		{
			irc_cmd_msg(session, jeux->config_prog->chan, _("ERREUR : Arguments invalides"));
			return;
		}



		//ouverture de la base de donnée et verification
		if (sqlite3_open_v2("DB", &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
		{
			fprintf(stderr, _("ERREUR : Impossible d'ouvrir la BDD dico : fermeture\n"));
			fprintf(stderr, "%s", sqlite3_errmsg(db));
			exit(EXIT_FAILURE);
		}
		else
		{
			sqlite3_stmt *requette = NULL;
			//verification de l'existance de la categorie
			erreur = sqlite3_prepare(db, "SELECT id FROM categorie WHERE categorie=?", -1, &requette, NULL);
			if (erreur == SQLITE_OK)
			{
				sqlite3_bind_text(requette, 1, categorie, -1, SQLITE_TRANSIENT);
				erreur = sqlite3_step(requette);

				//la categorie n'existe pas
				if (erreur != SQLITE_ROW)
				{
					irc_cmd_notice(session, origin, _("ERREUR : Catégorie inexistante"));
					sqlite3_close(db);
					free(mot);
					free(categorie);
					sqlite3_finalize(requette);
				}
				else
				{
					id_cat = sqlite3_column_int(requette, 0);
					sqlite3_finalize(requette);
				}
			}

			//verification de l'existance du mot !
			erreur =
			    sqlite3_prepare(db,
					    "SELECT mots.mot FROM  mots, categorie WHERE mots.mot=? AND mots.id_cat = categorie.id AND categorie.categorie=? ",
					    -1, &requette, NULL);
			if (erreur == SQLITE_OK)
			{
				sqlite3_bind_text(requette, 1, mot, -1, SQLITE_TRANSIENT);
				sqlite3_bind_text(requette, 2, categorie, -1, SQLITE_TRANSIENT);
				erreur = sqlite3_step(requette);
				sqlite3_finalize(requette);

				//le mot existe : message d'erreur a l'utilisateur
				if (erreur == SQLITE_ROW)
				{
					irc_cmd_notice(session, origin, _("ERREUR : Le mot existe"));
					sqlite3_close(db);
					free(mot);
				}
				//le mot n'existe pas ...
				else
				{
					//ajouit du mot 
					char *phrase =
					    (char *) g_strdup_printf("INSERT INTO mots(mot, id_cat, deja_tire) VALUES('%s',%d,0)", mot, id_cat);
					erreur = sqlite3_prepare(db, phrase, -1, &requette, NULL);
					g_free(phrase);
					if (erreur == SQLITE_OK)
					{
						sqlite3_step(requette);
						sqlite3_finalize(requette);
						sqlite3_close(db);
						free(mot);
						irc_cmd_notice(session, origin, "Mot ajouté.");
					}
					//erreur a l'ajout du mot : report de l'erreur et fermeture
					else
					{
						sqlite3_close(db);
						free(mot);
						fprintf(stderr, _("ERREUR : Impossible d'ajouter le mot a la BDD\n"));
						exit(EXIT_FAILURE);
					}
				}
			}
			//erreur lors de la vérification de l'existance : code d'erreur
			else
			{
				fprintf(stderr, _("ERREUR : Impossible de vérifier l'existence d'un mot : fermeture\n"));
				free(mot);
				sqlite3_close(db);
				exit(EXIT_FAILURE);
			}
		}
	}
}

void cmd_retirer(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		char *mot = NULL;
		char *categorie = NULL;
		int erreur = 0;

		erreur = recuperer_args_ajouter(&params[1][taille_cmd + 1], &categorie, &mot);
		if (erreur)
		{
			irc_cmd_msg(session, jeux->config_prog->chan, _("ERREUR : Arguments invalides"));
		}
		else
		{
			int nb_exec_requette = 0;
			sqlite3 *db = NULL;

			//copie du mot et suppresion des espaces
			couper_espace(mot);

			//ouverture de la db et vérification
			if (sqlite3_open_v2("DB", &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
			{
				fprintf(stderr, _("ERREUR : Impossible d'ouvrir la BDD dico : fermeture\n"));
				fprintf(stderr, "%s", sqlite3_errmsg(db));
				exit(EXIT_FAILURE);
			}
			else
			{
				char *msg_erreur = NULL;
				char *requette = NULL;

				//suppression du mot
				requette =
				    (char *)
				    g_strdup_printf
				    ("delete from mots where id in (select mots.id from mots, categorie where mots.mot = '%s' and mots.id_cat = categorie.id and categorie.categorie = '%s')",
				     mot, categorie);
				erreur = sqlite3_exec(db, requette, NULL, NULL, &msg_erreur);
				g_free(requette);
				free(mot);

				//la requette s'es mal passer
				if (erreur != SQLITE_OK)
				{
					fprintf(stderr, "%s", msg_erreur);
					sqlite3_free(msg_erreur);
					sqlite3_close(db);
					exit(EXIT_FAILURE);
				}
				//la requette s'es bien passer
				else
				{
					int nb_changement = sqlite3_changes(db);
					sqlite3_close(db);

					//verification si le mot existait : et envois d'état
					if (nb_changement == 0)
					{
						irc_cmd_notice(session, origin, _("ERREUR : Le mot n'existe pas"));
					}
					else if (nb_changement == 1)
					{
						irc_cmd_notice(session, origin, _("Mot supprimé."));
					}
					//plus de une ligne modifié : erreur
					else
					{
						irc_cmd_msg(session, jeux->config_prog->chan,
							    _("Attention : Base de données partiellement corrompue : fermeture"));
						exit(EXIT_FAILURE);
					}
				}
			}
		}
	}
}

void cmd_password(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (strcmp(jeux->pseudo_leader, origin) != 0)
	{
		irc_cmd_kick(session, origin, jeux->config_prog->chan, _("Tentative de hack"));
	}
	else
	{
		//comptage de la taille du mdp et alocation dynamique
		int taille_mdp = strlen(&params[1][taille_cmd + 1]);
		char *password = NULL;
		password = malloc(sizeof(char) * (taille_mdp + 1));

		if (password == NULL)
		{
			fprintf(stderr, _("ERREUR : impossible d'alouer la mémoire pour le mot de passe : fermeture"));
			exit(EXIT_FAILURE);
		}
		else
		{
			//copie du mdp, supprision des espace de chaine
			strcpy(password, &params[1][taille_cmd + 1]);
			couper_espace(password);

			//calcul de la somme de controle du mdp
			char *somme_sha1 = sha1sun(password);
			printf(_("DEBUG : Somme de contrôle : %s\n"), somme_sha1);
			//comparaison de la somme de controle
			if (strcmp(somme_sha1, jeux->config_prog->password) == 0)
			{
				char *phrase = NULL;
				//validation du mdp
				jeux->password_valider = 1;
				irc_cmd_notice(session, origin, _("Mot de passe accepté."));
				//passage du mode halfop
				phrase = (char *) g_strdup_printf("+h %s", jeux->config_prog->pseudo_leader);
				irc_cmd_channel_mode(session, jeux->config_prog->chan, phrase);
				g_free(phrase);
			}
			else
			{
				irc_cmd_notice(session, origin, _("Mot de passe refusé."));
			}
			free(somme_sha1);
			free(password);
		}
	}
}

void cmd_debut_jeux(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_LEADER | NEED_ADMIN))
	{
		if (jeux->inscription_ouverte == 0)
		{
			irc_cmd_msg(session, jeux->config_prog->chan,
				    _("\x02\00305Opération impossible : veuillez lancer les inscription au préalable."));
		}
		else
		{
			int i = 0;
			int no_joueur_qui_commence = -1;
			char *mot = NULL;
			char *phrase = NULL;
			participent *info_joueur_qui_commence = NULL;
			//definition du mode en cour de jeux
			jeux->inscription_ouverte = 0;
			jeux->parti_en_cour = 1;
			//tirage au sort du mot et du joueur
			no_joueur_qui_commence = rand() % jeux->nb_inscrits;
			printf(_("DEBUG : Joueur %d commence\n"), no_joueur_qui_commence);
			jeux->mot_a_deviner = tirer_un_mot(jeux->config_prog->def_cat);
			//selection du joueur par son no
			info_joueur_qui_commence = jeux->joueurs;
			for (i = 0; i != no_joueur_qui_commence; i++)
			{
				info_joueur_qui_commence = info_joueur_qui_commence->joueur_suivent;
			}

			//passage du canal en mode modered
			irc_cmd_channel_mode(session, jeux->config_prog->chan, "+m");
			irc_cmd_msg(session, jeux->config_prog->chan,
				    _("\x02\00308Le salon passe en mode moderé, seuls les joueurs et admins peuvent parler."));
			//copie du pseudo du joueur compteur
			strcpy(jeux->pseudo_compteur, info_joueur_qui_commence->pseudo);
			//envois du mot au joueur et au leader
			phrase = (char *) g_strdup_printf(_("\x02Le mot à faire deviner est : %s"), jeux->mot_a_deviner);
			irc_cmd_notice(session, info_joueur_qui_commence->pseudo, phrase);
			if (jeux->pseudo_joueur_leader)
			{
				irc_cmd_notice(session, jeux->pseudo_joueur_leader, phrase);
			}
			irc_cmd_notice(session, jeux->pseudo_leader, phrase);
			g_free(phrase);
			//envois du message de commancement de jeux sur le canal
			phrase = (char *) g_strdup_printf(_("\002C'est %s qui fait deviner."), info_joueur_qui_commence->pseudo);
			irc_cmd_msg(session, jeux->config_prog->chan, phrase);
			g_free(phrase);
			//initialisation du thread timeout
			init_thread_timeout(jeux, origin, session);
		}
	}
}

void cmd_ajouter_cat(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		int taille_cat = strlen(&params[1][taille_cmd + 1]);
		char *categorie = NULL;
		categorie = malloc(sizeof(char) * (taille_cat + 1));
		//verification si le mot est bien alouer
		if (categorie == NULL)
		{
			fprintf(stderr, _("ERREUR : Impossible d'allouer de la mémoire : fermeture"));
			exit(EXIT_FAILURE);
		}
		else
		{
			sqlite3 *db = NULL;
			//recuperation du nom de la categorie
			strcpy(categorie, &params[1][taille_cmd + 1]);
			couper_espace(categorie);
			//ouverture de la bdd et fermeture en cas d'erreur d'ouverture
			if (sqlite3_open_v2("DB", &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
			{
				fprintf(stderr, _("ERREUR : Impossible d'ouvrir la BDD : fermeture\n"));
				fprintf(stderr, "%s", sqlite3_errmsg(db));
				free(categorie);
				exit(EXIT_FAILURE);
			}
			else
			{
				int erreur = 0;
				char *msg_erreur = NULL;
				char *requette = (char *) g_strdup_printf("INSERT INTO categorie(categorie) VALUES('%s')", categorie);
				free(categorie);
				//tentative d'insertion
				erreur = sqlite3_exec(db, requette, NULL, NULL, &msg_erreur);
				free(requette);
				//la categorie existe
				if (erreur == SQLITE_CONSTRAINT)
				{
					irc_cmd_msg(session, jeux->config_prog->chan, _("ERREUR : La catégorie existe"));
				}
				//la requette s'es mal passer : fermeture
				else if (erreur != SQLITE_OK)
				{
					fprintf(stderr, "%d\n%s\n", erreur, msg_erreur);
					sqlite3_free(msg_erreur);
					sqlite3_close(db);
					exit(EXIT_FAILURE);
				}
				//la requette s'es bien passer
				else
				{
					irc_cmd_msg(session, jeux->config_prog->chan, _("Catégorie ajoutée."));
				}
			}
		}
	}
}

void cmd_retirer_cat(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		int taille_cat = strlen(&params[1][taille_cmd + 1]);
		char *categorie = NULL;
		categorie = malloc(sizeof(char) * (taille_cat + 1));
		//verification si la viariable est bien alouer
		if (categorie == NULL)
		{
			fprintf(stderr, _("ERREUR : Mémoire insufissante : fermeture"));
			exit(EXIT_FAILURE);
		}
		else
		{
			sqlite3 *db = NULL;
			//recupération du nom de la catégorie
			strcpy(categorie, &params[1][taille_cmd + 1]);
			couper_espace(categorie);
			//ouverture de la db : fermeture en cas d'erreur
			if (sqlite3_open_v2("DB", &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
			{
				fprintf(stderr, _("ERREUR : Impossible d'ouvrir la BDD : fermeture\n"));
				fprintf(stderr, "%s\n", sqlite3_errmsg(db));
				free(categorie);
				exit(EXIT_FAILURE);
			}
			else
			{
				int erreur = 0;
				char *msg_erreur = NULL;
				char *requette = (char *) g_strdup_printf("DELETE FROM mots WHERE id_cat in"
									  "(SELECT id FROM categorie WHERE categorie = '%s');"
									  "DELETE FROM categorie WHERE categorie = '%s'\n;",
									  categorie, categorie);
				erreur = sqlite3_exec(db, requette, NULL, NULL, &msg_erreur);
				g_free(requette);
				free(categorie);
				//la requette s'es mal passé
				if (erreur != SQLITE_OK)
				{
					fprintf(stderr, _("ERREUR : Impossible de supprimer la catégorie \n%s\n"), msg_erreur);
					sqlite3_free(msg_erreur);
					sqlite3_close(db);
					exit(EXIT_FAILURE);
				}
				else
				{
					int nb_changement = sqlite3_changes(db);
					sqlite3_close(db);
					if (nb_changement > 0)
					{
						irc_cmd_msg(session, jeux->config_prog->chan, _("Catégorie supprimée."));
					}
					else
					{
						irc_cmd_msg(session, jeux->config_prog->chan, _("ERREUR : Catégorie inexistante"));
					}
				}
			}
		}
	}
}

void cmd_changer_cat(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	if (verifier_leader(jeux, origin, session, NEED_ADMIN))
	{
		int taille_categorie = strlen(&params[1][taille_cmd + 1]);
		char *categorie = NULL;
		//alocation de mémoire pour la categorie
		categorie = malloc(sizeof(char) * (taille_categorie + 1));
		if (categorie == NULL)
		{
			fprintf(stderr, _("ERREUR : Impossible d'allouer de la mémoire pour la catégorie : fermeture"));
			exit(EXIT_FAILURE);
		}
		else
		{
			sqlite3 *db = NULL;
			//copie de la categorie
			strcpy(categorie, &params[1][taille_cmd + 1]);
			couper_espace(categorie);
			if (sqlite3_open_v2("DB", &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
			{
				fprintf(stderr, _("ERREUR : Impossible d'ouvrir la BDD\n%s\n"), sqlite3_errmsg(db));
				free(categorie);
				exit(EXIT_FAILURE);
			}
			else
			{
				int nb_row = 0;
				int erreur = 0;
				char *err_msg = NULL;
				char *requette = (char *) g_strdup_printf("SELECT * FROM categorie WHERE categorie='%s'", categorie);
				printf(_("DEBUG : pointeur nb_row %p   %d\n"), &nb_row, nb_row);
				erreur = sqlite3_exec(db, requette, compter_colonnes, &nb_row, &err_msg);
				sqlite3_close(db);
				g_free(requette);
				//la requette s'es mal passé
				if (erreur != SQLITE_OK)
				{
					fprintf(stderr, _("ERREUR : Impossible de vérifier l'existence de la catégorie\n%s\n"), err_msg);
					sqlite3_free(err_msg);
					free(categorie);
					exit(EXIT_FAILURE);
				}
				//la requette s'es bien passé
				else
				{
					if (nb_row == 0)
					{
						irc_cmd_msg(session, jeux->config_prog->chan, _("ERREUR : La catégorie n'existe pas"));
						free(categorie);
					}
					else if (nb_row == 1)
					{
						free(jeux->config_prog->def_cat);
						jeux->config_prog->def_cat = categorie;
						irc_cmd_msg(session, jeux->config_prog->chan, _("Catégorie changée."));
					}
					else
					{
						fprintf(stderr, _("Base de données corrompu : veuillez fixer ça à la main\n"));
						free(categorie);
						exit(EXIT_FAILURE);
					}
				}
			}
		}
	}
}

void cmd_score_total(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	sqlite3 *db = NULL;
	if (sqlite3_open_v2("DB", &db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK)
	{
		fprintf(stderr, _("ERREUR : Impossible d'ouvrir la BDD : fermeture\n%s\n"), sqlite3_errmsg(db));
		exit(EXIT_FAILURE);
	}
	else
	{
		int i = 1;
		sqlite3_stmt *requette = NULL;
		sqlite3_prepare_v2(db, "SELECT pseudo,score FROM utilisateur ORDER BY score desc", -1, &requette, NULL);
		while (sqlite3_step(requette) == SQLITE_ROW)
		{
			int score = -1;
			char *phrase = NULL;
			const unsigned char *pseudo = sqlite3_column_text(requette, 0);
			score = sqlite3_column_int(requette, 1);
			phrase = (char *) g_strdup_printf("%d ) %s : %d", i, pseudo, score);
			irc_cmd_notice(session, origin, phrase);
			g_free(phrase);
			i++;
		}
		sqlite3_finalize(requette);
		sqlite3_close(db);
	}
}

void cmd_hlme(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	bool hl_me = false;
	sqlite3 *db = NULL;
	//parsing des arguments
	if (!strcmp(_("oui"), &params[1][taille_cmd + 1]) || !strcmp(_("on"), &params[1][taille_cmd + 1]))
	{
		hl_me = true;
	}
	else if (!strcmp(_("non"), &params[1][taille_cmd + 1]) ||
		 !strcmp(_("off"), &params[1][taille_cmd + 1]) || !strcmp("", &params[1][taille_cmd + 1]))
	{
		hl_me = false;
	}
	else
	{
		irc_cmd_notice(session, origin, _("ERREUR : Argument invalide"));
	}

	//ouverture de la db
	if (sqlite3_open_v2("DB", &db, SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK)
	{
		char *msg_err = NULL;
		int erreur = 0;
		char *requette = (char *) g_strdup_printf("UPDATE utilisateur SET hl_me=%d WHERE pseudo='%s'", hl_me, origin);
		erreur = sqlite3_exec(db, requette, NULL, NULL, &msg_err);
		g_free(requette);
		if (erreur != SQLITE_OK)
		{
			fprintf(stderr, _("Erreur lors du changement : fermeture\n%s\n"), msg_err);
			sqlite3_free(msg_err);
			sqlite3_close(db);
			exit(EXIT_FAILURE);
		}
		else if (sqlite3_changes(db) == 0)
		{
			requette = (char *) g_strdup_printf("INSERT INTO utilisateur(pseudo, hl_me) VALUES('%s', %d)", origin, hl_me);
			erreur = sqlite3_exec(db, requette, NULL, NULL, &msg_err);
			g_free(requette);
			if (erreur != SQLITE_OK)
			{
				fprintf(stderr, _("Erreurs lors du changement : fermeture \n%s\n"), msg_err);
				sqlite3_free(msg_err);
				exit(EXIT_FAILURE);
			}
		}
		irc_cmd_notice(session, origin, _("Opération effectuée."));
		sqlite3_close(db);
	}
	else
	{
		fprintf(stderr, _("ERREUR : impossible d'ouvrir la BDD\n%s\n"), sqlite3_errmsg(db));
		exit(EXIT_FAILURE);
	}
}

void valider_pseudo(irc_session_t * session, donnee_de_control * jeux, const char *pseudo_a_valider)
{
	int i = 0;
	char *phrase = NULL;
	participent *joueur_a_incrementer = jeux->joueurs;
	for (i = 0; i != jeux->nb_inscrits; i++)
	{
		printf(_("DEBUG : Itération\n"));
		printf(_("DEBUG : Pseudo : %s,%s,\n"), pseudo_a_valider, joueur_a_incrementer->pseudo);
		printf(_("DEBUG : Retour de strcmp : %d\n"), strcmp(pseudo_a_valider, joueur_a_incrementer->pseudo));
		if (strcmp(pseudo_a_valider, joueur_a_incrementer->pseudo) == 0)
		{
			//affichage du gagnent  
			phrase = (char *) g_strdup_printf(_("\x02\00302Le gagnant est : %s"), joueur_a_incrementer->pseudo);
			irc_cmd_msg(session, jeux->config_prog->chan, phrase);
			g_free(phrase);
			//affichage du mot
			phrase = (char *) g_strdup_printf(_("\x02\00302Le mot était : %s"), jeux->mot_a_deviner);
			irc_cmd_msg(session, jeux->config_prog->chan, phrase);
			g_free(phrase);
			//validation du pseudo et inversion du role
			joueur_a_incrementer->points++;
			strcpy(jeux->pseudo_compteur, joueur_a_incrementer->pseudo);
			jeux->mot_a_deviner = tirer_un_mot(jeux->config_prog->def_cat);
			//envois du mot au joueur et au leader
			phrase = (char *) g_strdup_printf(_("\x02Le mot a faire deviner est : %s"), jeux->mot_a_deviner);
			irc_cmd_notice(session, joueur_a_incrementer->pseudo, phrase);
			irc_cmd_notice(session, jeux->pseudo_leader, phrase);
			if (jeux->pseudo_joueur_leader)
			{
				irc_cmd_notice(session, jeux->pseudo_joueur_leader, phrase);
			}

			g_free(phrase);
			jeux->nb_passer = 0;
			//initialisation du thread
		init_thread_timeout(jeux, jeux->pseudo_leader, session);
			return;
		}
		else
		{
			joueur_a_incrementer = joueur_a_incrementer->joueur_suivent;
		}
	}
}

void cmd_aide(donnee_de_control * jeux, const char *origin, irc_session_t * session, const char **params, size_t taille_cmd)
{
	//verification du mode de listage
	char* nomcmd = (char*) g_strdup_printf("%s", &params[1][taille_cmd + 1]);
	trie_commandes_t* commande  = rechercher_commandes(nomcmd, jeux->commandes, jeux->nb_commandes);

	if (commande)
	{ 
		//il sagis d'une description longue
		char* phrase = (char*) g_strdup_printf("%s : %s", commande->nom_commande, commande->long_desc);
		irc_cmd_notice(session, origin, phrase);
	}
	else
	{
		int i = 0;
		for (i = 0; i != jeux->nb_commandes; i++)
		{
			char * phrase = (char*) g_strdup_printf("%s : %s", jeux->commandes[i].nom_commande, jeux->commandes[i].short_desc);
			int erreur;
			printf("DEBUG : %s\n", phrase);
			erreur = irc_cmd_notice(session, origin, phrase);
			printf("DEBUG : %d\n", erreur);
			if (erreur)
			{
				printf("DEBUG : %d\n", irc_errno(session));
			}
			g_free(phrase);
			sleep(1);
		}
	}
}
